#include "DRAN.h"
#include <iostream>
#include <cstdlib>
#include <assert.h>

using namespace std;

#define INIT_USER 10

unsigned int userCount = 0;
TIME now, end;



/*---------------- Application Parameters ---------------*/
#define VIDEO_PROB 19
// Target Delay
TIME VoIP_delay = 200; // 100 ms delay
TIME Video_delay = 4000; // 2 s delay
// Duration
TIME VoIP_duration = 600000; // 5 minute phone call
TIME Video_duration = 60000; // 30 seconds video loading



/*---------------- Stats ---------------*/
int VoIP_count = 0;
int Video_count = 0;


/*---------------- RRH ----------------*/

// init
void RRH::Init() {
  bs[0].active = 1;
  bs[0].URBCap = 60*3;
  bs[0].DRBCap = 60*3;
  bs[0].delay = 0;

  for(int i=1; i<MAX_BS; i++) {
    bs[i].active = 0;
    bs[i].URBCap = 60*2;
    bs[i].DRBCap = 60*2;
    bs[i].delay = 1;
  }

  // start with INIT_USER users;
  for(int i=0; i<INIT_USER; i++)
    UserGen();
}

// user generation
void RRH::UserGen() {
  Bearer* myBearer = new Bearer;
  VoIP_count++;

  if (rand()%100 <= VIDEO_PROB)
    myBearer->application.Init(VIDEO);
  else
    myBearer->application.Init(VOIP);

  myBearer->BSID = -1;
  myBearer->userID = ++userCount;

  myBearer->last_rate = 1000;
  myBearer->bits_sent = 0;
  myBearer->bits_received = 0;
  myBearer->created_time = now;

  bearers.push_back(myBearer);
}

// request generation
void RRH::RequestGen() {
  for(unsigned int i=0; i<bearers.size(); i++) {
    bearers[i]->RequestGen();
  }
}


/*---------------- Bearer ----------------*/

void Bearer::RequestGen() {
  // request transmission every 1 second
  // target at transmitting 1500 K bits every requests
  // video size ~ 10 MB loaded in 30 secs
  if (application.type == VIDEO &&
      (now-created_time)%2000 == 0) {
    TransportBlock* t = new TransportBlock(VIDEO, REQUEST);
    blocks.push_back(t);
  }

  // request transmission every 20 ms
  // target at transmitting 4 bits every requests
  // voice size ~ 7.3 MB during 5 minutes
  else if (application.type == VOIP &&
      (now - created_time)%40 == 0) {
    TransportBlock* t = new TransportBlock(VOIP, REQUEST);
    blocks.push_back(t);
  }
}

/*---------------- Transport Block ----------------*/

TransportBlock::TransportBlock(AppType, BlockType) {
}

/*---------------- Application  ----------------*/
void Application::Init(AppType t) {
  if (t == VIDEO) {
    type = VIDEO;
    duration = Video_duration;
    targetDelay = Video_delay;
  }
  else if (t == VOIP) {
    type = VOIP;
    duration = VoIP_duration;
    targetDelay = VoIP_delay;
  }
  else
    assert(0);
}
